python, 전처리, 통계, 가설검정, 기계학습, 회귀, 분류, 군집, 모델 학습, 모델 평가
범주형 데이터 인코딩(Categorical Encoding)은 범주형 변수를 머신러닝 모델이 처리할 수 있는 수치형으로 변환하는 과정이다. 대부분의 머신러닝 알고리즘은 수치형 데이터만 입력으로 받을 수 있으므로, 범주형 변수를 적절히 인코딩하는 것은 필수적이다. 인코딩 방법의 선택은 데이터의 특성과 사용할 모델에 따라 달라지며, 잘못된 선택은 모델 성능을 크게 저하시킬 수 있다. 이 장에서는 Label Encoding, One-Hot Encoding, Ordinal Encoding, Target Encoding, Frequency Encoding 등 주요 인코딩 기법을 학습한다.
예제: 데이터 로드
import seaborn as snsimport pandas as pdimport numpy as np# 데이터 로드df = sns.load_dataset("penguins")# 범주형 변수 확인print("범주형 변수:")print(df.select_dtypes(include='object').columns.tolist())print("\n범주형 변수의 고유값 개수:")print(df.select_dtypes(include='object').nunique())
범주형 변수:
['species', 'island', 'sex']
범주형 변수의 고유값 개수:
species 3
island 3
sex 2
dtype: int64
7.1 Label Encoding
Label Encoding은 각 범주를 정수 값으로 매핑하는 가장 단순한 인코딩 방법이다. 예를 들어, “Adelie”, “Chinstrap”, “Gentoo”를 0, 1, 2로 변환한다. 구현이 간단하고 컬럼 수가 늘어나지 않는 장점이 있지만, 순서가 없는 범주에 순서를 부여하는 문제가 있다.
변환 예시
원본
인코딩 결과
Adelie
0
Chinstrap
1
Gentoo
2
7.1.1 예제 코드
예제: Label Encoding 적용
from sklearn.preprocessing import LabelEncoder# Label Encoder 생성le = LabelEncoder()# 데이터 복사df_label = df.copy()# species 컬럼 인코딩df_label["species_enc"] = le.fit_transform(df_label["species"])# 결과 확인print("Label Encoding 결과:")print(df_label[["species", "species_enc"]].head(10))# 매핑 관계 확인print("\n매핑 관계:")for i, label inenumerate(le.classes_):print(f"{label} → {i}")
Label Encoding은 범주 간에 순서 관계가 없음에도 불구하고 숫자로 변환하므로, 모델이 숫자의 크기를 의미 있는 것으로 해석할 수 있다. 예를 들어, 모델이 “Gentoo(2)”가 “Adelie(0)”보다 2배 크다고 잘못 학습할 수 있다.
사용 시점
트리 기반 모델(Decision Tree, Random Forest, XGBoost, LightGBM) 사용 시
컬럼 수를 늘리고 싶지 않을 때
범주의 개수가 매우 많을 때 (고차원 문제 완화)
트리 기반 모델은 범주를 분할 기준으로만 사용하므로 숫자의 크기를 의미 있게 해석하지 않는다.
7.2 One-Hot Encoding
One-Hot Encoding은 각 범주를 이진 컬럼으로 분리하는 방법이다. k개의 범주가 있으면 k개의 새로운 컬럼이 생성되며, 각 행은 해당 범주에 해당하는 컬럼에만 1을, 나머지에는 0을 갖는다. 이 방법은 범주 간 순서 관계를 만들지 않으므로 선형 모델과 거리 기반 모델에 가장 안전하다.
변환 예시
원본
species_Adelie
species_Chinstrap
species_Gentoo
Adelie
1
0
0
Chinstrap
0
1
0
Gentoo
0
0
1
7.2.1 pandas 방식
pandas의 get_dummies 함수를 사용하면 간단하게 One-Hot Encoding을 수행할 수 있다.
예제: One-Hot Encoding 적용
# One-Hot Encoding (모든 범주 유지)df_ohe = pd.get_dummies( df, columns=["species", "island"], drop_first=False)print("One-Hot Encoding 결과 (컬럼 목록):")print(df_ohe.columns.tolist())print(f"\n원본 컬럼 수: {len(df.columns)}")print(f"인코딩 후 컬럼 수: {len(df_ohe.columns)}")# 결과 샘플 확인print("\n인코딩 결과 (상위 5개):")print(df_ohe.head())
drop_first=True로 설정하면 첫 번째 더미 변수를 제거하여 다중공선성(multicollinearity)을 방지할 수 있다. 예를 들어, 3개의 종이 있으면 2개의 컬럼만으로도 모든 정보를 표현할 수 있다.
예제: drop_first 옵션 사용
# 첫 번째 더미 변수 제거df_ohe_drop = pd.get_dummies( df, columns=["species"], drop_first=True)print("drop_first=True 결과:")print(df_ohe_drop.filter(like='species').columns.tolist())
실무에서는 여러 범주형 컬럼을 동시에 처리해야 하는 경우가 많다. 각 인코딩 방법을 여러 컬럼에 적용하는 방법을 살펴본다.
7.6.1 One-Hot Encoding (여러 컬럼)
예제: 여러 컬럼 One-Hot Encoding
# 인코딩할 범주형 컬럼 목록cat_cols = ["species", "island", "sex"]# 여러 컬럼에 One-Hot Encoding 적용df_ohe_multi = pd.get_dummies( df, columns=cat_cols, drop_first=True# 다중공선성 방지)print("인코딩된 컬럼 목록:")print([col for col in df_ohe_multi.columns ifany(cat in col for cat in cat_cols)])print(f"\n원본 컬럼 수: {len(df.columns)}")print(f"인코딩 후 컬럼 수: {len(df_ohe_multi.columns)}")
from sklearn.preprocessing import LabelEncoder# 데이터 복사df_label_multi = df.copy()# 범주형 컬럼 목록cat_cols = ["species", "island", "sex"]# 각 컬럼에 Label Encoding 적용for col in cat_cols: le = LabelEncoder()# 결측치를 문자열로 변환하여 처리 df_label_multi[col] = le.fit_transform(df_label_multi[col].astype(str))print("Label Encoding 결과:")print(df_label_multi[cat_cols].head())
Label Encoding 결과:
species island sex
0 0 2 1
1 0 2 0
2 0 2 0
3 0 2 2
4 0 2 0
7.6.3 sklearn ColumnTransformer 사용
여러 인코딩 방법을 조합하여 사용하는 경우 ColumnTransformer를 사용하면 깔끔하게 처리할 수 있다.
예제: ColumnTransformer로 여러 인코딩 조합
from sklearn.compose import ColumnTransformerfrom sklearn.preprocessing import OneHotEncoder, LabelEncoder# 인코딩 파이프라인 구성ct = ColumnTransformer( transformers=[ ("ohe", OneHotEncoder(drop='first', sparse_output=False), ["species", "island"]),# LabelEncoder는 ColumnTransformer와 직접 사용 불가 ], remainder='passthrough'# 나머지 컬럼은 그대로 유지)# 수치형 컬럼 선택num_cols = ["bill_length_mm","bill_depth_mm","flipper_length_mm","body_mass_g"]df_transformed = ct.fit_transform(df[["species", "island", "sex"] + num_cols].dropna())print("ColumnTransformer 변환 결과 shape:")print(df_transformed.shape)
ColumnTransformer 변환 결과 shape:
(333, 9)
7.7 요약
이 장에서는 범주형 데이터를 수치형으로 변환하는 다양한 인코딩 기법을 학습했다. 주요 내용은 다음과 같다.
인코딩 방법 비교
인코딩
순서 필요
컬럼 수 증가
장점
단점
추천 모델
Label
X
X
간단, 효율적
순서 관계 생성
트리 기반 모델
One-Hot
X
O
순서 없음, 안전
고차원 문제
선형, 거리 기반 모델
Ordinal
O
X
순서 정보 반영
순서 정의 필요
순서형 데이터
Target
X
X
정보량 큼
데이터 누수 위험
고급 트리 모델 (주의 필요)
Frequency
X
X
희귀 범주 처리
정보 손실 가능
희귀 범주가 많을 때
인코딩 방법 선택 가이드
트리 기반 모델: Label Encoding (간단하고 효율적)
선형/거리 기반 모델: One-Hot Encoding (가장 안전)
순서가 있는 범주: Ordinal Encoding (순서 정보 활용)
고차원 범주: Target Encoding 또는 Frequency Encoding (차원 증가 방지)
희귀 범주 많음: Frequency Encoding (희귀도 반영)
주의사항
데이터 누수 방지: Target Encoding 사용 시 학습/테스트 분리 철저히 지킬 것
다중공선성: One-Hot Encoding에서 선형 모델 사용 시 drop_first=True 권장
결측치 처리: 인코딩 전 결측치를 별도 범주로 처리하거나 제거할 것
새로운 범주: 테스트 데이터에 학습 시 없던 범주가 나타나면 처리 전략 필요
실무 인코딩 순서
범주형 변수 식별 및 순서 여부 확인
모델 유형에 따른 인코딩 방법 선택
학습/테스트 데이터 분리 (데이터 누수 방지)
학습 데이터로 인코더 학습(fit)
학습/테스트 데이터에 동일한 인코더 적용(transform)
범주형 데이터 인코딩은 전처리의 마지막 단계로, 적절한 방법을 선택하면 모델 성능을 크게 향상시킬 수 있다. 데이터의 특성, 모델의 요구사항, 범주의 개수와 순서 관계를 종합적으로 고려하여 최적의 인코딩 방법을 선택하는 것이 중요하다. 이제 데이터 전처리의 전 과정을 마쳤으며, 다음 단계로 정제된 데이터를 활용한 모델링을 진행할 수 있다.